﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Collections;
using System.ComponentModel;
using Medianamik.Core.Security;
using Medianamik.Core;
using Medianamik.Core.Sugar;
using Medianamik.Globalization;
using Medianamik.Core.Interfaces;

namespace Medianamik.UI.Controls
{
    [ToolboxData("<{0}:PermissionSelector runat=server></{0}:PermissionSelector>")]
    public class PermissionSelector : CompositeControl
    {

        #region Fields

        Repeater _repeater;

        #endregion

        #region Events

        protected void GroupRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if ((e.Item.ItemType == ListItemType.Item
                || e.Item.ItemType == ListItemType.AlternatingItem)
                && e.Item.DataItem != null)
            {
                InheritedPermission inheritedPermission = GetInheritedPermissionForGroup((IGroup)e.Item.DataItem);

                Permission permission = GetPermissionForGroup((IGroup)e.Item.DataItem);

                if (permission == null)
                {
                    ((GroupRadioButton)e.Item.FindControl("inheritedOption")).Checked = true;
                }
                else
                {
                    switch (permission.SecurityLevel)
                    {
                        case SecurityLevels.Deny:
                            ((GroupRadioButton)e.Item.FindControl("denyOption")).Checked = true;
                            break;
                        case SecurityLevels.Read:
                            ((GroupRadioButton)e.Item.FindControl("readOption")).Checked = true;
                            break;
                        case SecurityLevels.Update:
                            ((GroupRadioButton)e.Item.FindControl("updateOption")).Checked = true;
                            break;
                        case SecurityLevels.Create:
                            ((GroupRadioButton)e.Item.FindControl("createOption")).Checked = true;
                            break;
                        case SecurityLevels.Delete:
                            ((GroupRadioButton)e.Item.FindControl("deleteOption")).Checked = true;
                            break;
                        case SecurityLevels.Grant:
                            ((GroupRadioButton)e.Item.FindControl("grantOption")).Checked = true;
                            break;
                        default:
                            throw new Exception("Unknown security level: " + permission.SecurityLevel.ToString());
                    }
                }

                if (inheritedPermission == null)
                {
                    ((Literal)e.Item.FindControl("inheritedInfo")).Text = String.Format("{0} ({1})",
                        Translator.Translate("Medianamik_SecurityManagement", "NoInheritedSecurity"),
                        Translator.Translate("Medianamik_SecurityManagement", "Grant"));
                }
                else
                {
                    ((Literal)e.Item.FindControl("inheritedInfo")).Text = String.Format("{0} ({1})",
                        Translator.Translate("Medianamik_SecurityManagement", inheritedPermission.SecurityLevel.ToString()),
                        GetObjectName(inheritedPermission.InheritedFromObjectId));
                }
            }
        }

        #endregion

        #region Properties

        public Guid SecuredObjectId
        {
            get
            {
                object o = ViewState["ObjectId"];
                if (o == null)
                    throw new ArgumentNullException("Property ObjectId of PermissionSelector cannot be null.");
                return (Guid)o;
            }
            set { ViewState["ObjectId"] = value; }
        }

        protected IEnumerable<Group> Groups
        {
            get
            {
                if (_groups == null)
                {
                    _groups = ((MedianamikRoleProvider)Roles.Provider).GetAllIGroups().ToList() ;  
                    _groups.RemoveAll(g => g.ID.Equals(MedianamikGroups.SuperAdmins));
                }
                return _groups.AsEnumerable().OrderBy(g=>g.TranslatedName);
            }
        }
        List<Group> _groups;

        protected virtual PermissionType PermissionType
        {
            get { return PermissionType.TypePermission; }
        }

        public IEnumerable<Permission> Permissions
        {
            get
            {
                if (_permissions == null)
                {
                    _permissions = new List<Permission>();

                    foreach (RepeaterItem item in _repeater.Items)
                    {
                        Guid key;

                        if ((item.ItemType == ListItemType.Item ||
                            item.ItemType == ListItemType.AlternatingItem) &&
                            StringHelper.IsGuid(((HiddenField)item.FindControl("dataFieldId")).Value, out key))
                        {
                            GroupRadioButton denyOption = (GroupRadioButton)item.FindControl("denyOption");
                            GroupRadioButton readOption = (GroupRadioButton)item.FindControl("readOption");
                            GroupRadioButton updateOption = (GroupRadioButton)item.FindControl("updateOption");
                            GroupRadioButton createOption = (GroupRadioButton)item.FindControl("createOption");
                            GroupRadioButton deleteOption = (GroupRadioButton)item.FindControl("deleteOption");
                            GroupRadioButton grantOption = (GroupRadioButton)item.FindControl("grantOption");

                            if (denyOption != null && denyOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Deny,
                                    PermissionType));
                            }
                            else if (readOption != null && readOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Read,
                                    PermissionType));
                            }
                            else if (updateOption != null && updateOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Update,
                                    PermissionType));
                            }
                            else if (createOption != null && createOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Create,
                                    PermissionType));
                            }
                            else if (deleteOption != null && deleteOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Delete,
                                    PermissionType));
                            }
                            else if (grantOption != null && grantOption.Checked)
                            {
                                _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Grant,
                                    PermissionType));
                            }
                            //else if (((CheckBox)item.FindControl("groupCheckbox")).Checked)
                            //{
                            //    _permissions.Add(new Permission(SecuredObjectId, key, SecurityLevels.Inherited,
                            //        PermissionType, true));
                            //}
                        }
                    }
                }

                return _permissions;
            }
        }
        List<Permission> _permissions;

        private PermissionColumns _displayedPermissions = PermissionColumns.All;
        protected virtual PermissionColumns DisplayedPermissions
        {
            get { return _displayedPermissions; }
            set { _displayedPermissions = value; }
        }

        #endregion

        #region Methods

        #region Overriding

        protected override void CreateChildControls()
        {
            _repeater = new Repeater();

            Controls.Add(_repeater);

            //Create the templates
            _repeater.ItemTemplate = new PermissionSelectorItemTemplate(DisplayedPermissions);
            _repeater.HeaderTemplate = new PermissionSelectorHeaderTemplate(DisplayedPermissions);
            _repeater.FooterTemplate = new PermissionSelectorFooterTemplate();

            _repeater.ItemDataBound += new RepeaterItemEventHandler(GroupRepeater_ItemDataBound);
        }

        public override void DataBind()
        {
            EnsureChildControls();
            _repeater.DataSource = Groups;
            base.DataBind();
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            string jsPermissionSelector = Medianamik.Core.Sugar.Resources.GetResourceText("Controls.PermissionSelector.PermissionSelectorClientScript.js", this.GetType().Assembly);

            if (!String.IsNullOrEmpty(jsPermissionSelector))
            {
                ScriptManager.RegisterStartupScript(this, this.GetType(), "jsPermissionSelector", jsPermissionSelector, true);
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);

            writer.Write(String.Concat("<script type=\"text/javascript\">var controlClientID = '",
                this.ClientID, "';</script>"));
        }

        #endregion

        protected virtual string GetObjectName(Guid objectID)
        {
             return NodeTypeManager.GetNodeType(objectID).Name;
        }

        protected virtual InheritedPermission GetInheritedPermissionForGroup(IGroup group)
        {
            return SecurityManager.GetInheritedNodeTypePermissionsByGroupId(group.GroupId)
                    .SingleOrDefault(p => p.SecuredObjectId.Equals(SecuredObjectId));
        }

        protected virtual Permission GetPermissionForGroup(IGroup group)
        {
            return SecurityManager.GetNodeTypePermissionsByGroupId(group.GroupId )
                    .SingleOrDefault(p => p.SecuredObjectId.Equals(SecuredObjectId));
        }

        #endregion

        #region Inner Classes

        [Flags]
        public enum PermissionColumns : long
        {
            None = 0,
            Deny = 1,
            Read = 2,
            Update = 4,
            Create = 8,
            Delete = 16,
            Grant = 32,
            All = long.MaxValue
        }

        class PermissionSelectorHeaderTemplate : ITemplate
        {

            #region Fields

            Literal header = new Literal();
            Button applyToChildrenButton = new Button();
            PermissionColumns _displayedPermissions;

            #endregion

            #region .ctors

            public PermissionSelectorHeaderTemplate(PermissionColumns displayedPermissions)
            {
                _displayedPermissions = displayedPermissions;
            }

            #endregion

            #region Events



            #endregion

            #region Properties



            #endregion

            #region Methods

            public void InstantiateIn(System.Web.UI.Control container)
            {
                container.Controls.Add(header);

                StringBuilder headerBuilder = new StringBuilder("<table cellpadding=\"2\" cellspacing=\"2\" border=\"0\">");

                //Select Row
                //headerBuilder.AppendLine("<tr>");
                //headerBuilder.AppendLine("<td colspan=\"14\">");
                //headerBuilder.Append(Translator.Translate("Medianamik_SecurityManagement", "ApplyToChildrenSelect"));
                //headerBuilder.Append("&nbsp;");
                //headerBuilder.AppendFormat("<a href=\"#\" onclick=\"checkAllRadio(); return false;\">{0}</a>",
                //    Translator.Translate("Medianamik_Global", "All"));
                //headerBuilder.Append("&nbsp;");
                //headerBuilder.AppendFormat("<a href=\"#\" onclick=\"checkNoneRadio(); return false;\">{0}</a>\n",
                //    Translator.Translate("Medianamik_Global", "None"));
                //headerBuilder.AppendLine("</td>");
                //headerBuilder.AppendLine("</tr>");

                //Header Title Row
                headerBuilder.AppendLine("<tr>");
                headerBuilder.AppendLine("<td>&nbsp;</td>"); //Title + Checkbox

                int displayedColumns = 0;

                if ((_displayedPermissions & PermissionColumns.Deny) == PermissionColumns.Deny)
                {
                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Deny"));
                    displayedColumns++;
                }

                if ((_displayedPermissions & PermissionColumns.Read) == PermissionColumns.Read)
                {
                    if(displayedColumns > 0)
                        headerBuilder.AppendLine("<td>&nbsp;&gt;&nbsp;</td>");

                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Read"));
                    displayedColumns++;
                }

                if ((_displayedPermissions & PermissionColumns.Update) == PermissionColumns.Update)
                {
                    if (displayedColumns > 0)
                        headerBuilder.AppendLine("<td>&nbsp;&gt;&nbsp;</td>");

                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Update"));
                    displayedColumns++;
                }

                if ((_displayedPermissions & PermissionColumns.Create) == PermissionColumns.Create)
                {
                    if (displayedColumns > 0)
                        headerBuilder.AppendLine("<td>&nbsp;&gt;&nbsp;</td>");

                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Create"));
                    displayedColumns++;
                }

                if ((_displayedPermissions & PermissionColumns.Delete) == PermissionColumns.Delete)
                {
                    if (displayedColumns > 0)
                        headerBuilder.AppendLine("<td>&nbsp;&gt;&nbsp;</td>");

                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Delete"));
                    displayedColumns++;
                }

                if ((_displayedPermissions & PermissionColumns.Grant) == PermissionColumns.Grant)
                {
                    if (displayedColumns > 0)
                        headerBuilder.AppendLine("<td>&nbsp;&gt;&nbsp;</td>");

                    headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Grant"));
                    displayedColumns++;
                }

                if (displayedColumns > 0)
                    headerBuilder.AppendLine("<td>&nbsp;|&nbsp;</td>");

                headerBuilder.AppendFormat("<td>{0}</td>\n", Translator.Translate("Medianamik_SecurityManagement", "Inherit"));
                headerBuilder.AppendLine("<td>&nbsp;</td>"); //Inherited Info
                headerBuilder.AppendLine("<td>&nbsp;</td>"); //Item ID
                headerBuilder.AppendLine("</tr>");

                header.Text = headerBuilder.ToString();

            }

            #endregion

        }

        class PermissionSelectorFooterTemplate : ITemplate
        {

            #region Fields

            Literal footer = new Literal();

            #endregion

            #region Events



            #endregion

            #region Properties



            #endregion

            #region Methods

            public void InstantiateIn(System.Web.UI.Control container)
            {
                container.Controls.Add(footer);
                footer.Text = "</table>";
            }

            #endregion

        }

        class PermissionSelectorItemTemplate : ITemplate
        {

            #region Fields

            TableRow row;

            TableCell hiddenIDCell;
            HiddenField dataFieldId;

            TableCell checkboxCell;
            //CheckBox groupCheckbox;
            Literal groupName;

            TableCell denyOptionCell;
            GroupRadioButton denyOption;

            TableCell readOptionCell;
            GroupRadioButton readOption;

            TableCell updateOptionCell;
            GroupRadioButton updateOption;

            TableCell createOptionCell;
            GroupRadioButton createOption;

            TableCell deleteOptionCell;
            GroupRadioButton deleteOption;

            TableCell grantOptionCell;
            GroupRadioButton grantOption;

            TableCell inheritedOptionCell;
            GroupRadioButton inheritedOption;

            TableCell inheritedInfoCell;
            Literal inheritedInfo;

            TableCell td;

            PermissionColumns _displayedPermissions;

            #endregion

            #region .ctors

            public PermissionSelectorItemTemplate(PermissionColumns displayedPermissions)
            {
                _displayedPermissions = displayedPermissions;
            }

            #endregion

            #region Events

            private void BindDataFieldId(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)dataFieldId.NamingContainer;
                var group = ((IGroup)container.DataItem);
                dataFieldId.Value = group.GroupId .ToString();
            }

            //private void BindCheckbox(Object s, EventArgs e)
            //{
            //    RepeaterItem container = (RepeaterItem)groupCheckbox.NamingContainer;
            //    var group = ((IGroup)container.DataItem);
            //    groupCheckbox.Text = group.GroupName ;
            //}

            private void BindGroupName(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)groupName.NamingContainer;
                var group = ((IGroup)container.DataItem);
                groupName.Text = group.GroupName;
            }

            private void BindDenyOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)denyOption.NamingContainer;
                denyOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindReadOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)readOption.NamingContainer;
                readOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindUpdateOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)updateOption.NamingContainer;
                updateOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindCreateOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)createOption.NamingContainer;
                createOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindDeleteOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)deleteOption.NamingContainer;
                deleteOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindGrantOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)grantOption.NamingContainer;
                grantOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            private void BindInheritedOption(Object s, EventArgs e)
            {
                RepeaterItem container = (RepeaterItem)inheritedOption.NamingContainer;
                inheritedOption.GroupName = "optionGroup" + container.ItemIndex.ToString();
            }

            #endregion

            #region Properties



            #endregion

            #region Methods

            public void InstantiateIn(System.Web.UI.Control container)
            {
                row = new TableRow();

                container.Controls.Add(row);

                checkboxCell = new TableCell();
                row.Cells.Add(checkboxCell);
                groupName = new Literal();
                groupName.DataBinding += new EventHandler(BindGroupName);
                groupName.ID = "groupName";
                checkboxCell.Controls.Add(groupName);
                //groupCheckbox = new CheckBox();
                //groupCheckbox.DataBinding += new EventHandler(BindCheckbox);
                //groupCheckbox.ID = "groupCheckbox";
                //checkboxCell.Controls.Add(groupCheckbox);

                if ((_displayedPermissions & PermissionColumns.Deny) == PermissionColumns.Deny)
                {
                    denyOptionCell = new TableCell();
                    row.Cells.Add(denyOptionCell);
                    denyOptionCell.Style.Add("text-align", "center");
                    denyOption = new GroupRadioButton();
                    denyOption.DataBinding += new EventHandler(BindDenyOption);
                    denyOption.ID = "denyOption";
                    denyOptionCell.Controls.Add(denyOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                if ((_displayedPermissions & PermissionColumns.Read) == PermissionColumns.Read)
                {
                    readOptionCell = new TableCell();
                    row.Cells.Add(readOptionCell);
                    readOptionCell.Style.Add("text-align", "center");
                    readOption = new GroupRadioButton();
                    readOption.DataBinding += new EventHandler(BindReadOption);
                    readOption.ID = "readOption";
                    readOptionCell.Controls.Add(readOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                if ((_displayedPermissions & PermissionColumns.Update) == PermissionColumns.Update)
                {
                    updateOptionCell = new TableCell();
                    row.Cells.Add(updateOptionCell);
                    updateOptionCell.Style.Add("text-align", "center");
                    updateOption = new GroupRadioButton();
                    updateOption.DataBinding += new EventHandler(BindUpdateOption);
                    updateOption.ID = "updateOption";
                    updateOptionCell.Controls.Add(updateOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                if ((_displayedPermissions & PermissionColumns.Create) == PermissionColumns.Create)
                {
                    createOptionCell = new TableCell();
                    row.Cells.Add(createOptionCell);
                    createOptionCell.Style.Add("text-align", "center");
                    createOption = new GroupRadioButton();
                    createOption.DataBinding += new EventHandler(BindCreateOption);
                    createOption.ID = "createOption";
                    createOptionCell.Controls.Add(createOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                if ((_displayedPermissions & PermissionColumns.Delete) == PermissionColumns.Delete)
                {
                    deleteOptionCell = new TableCell();
                    row.Cells.Add(deleteOptionCell);
                    deleteOptionCell.Style.Add("text-align", "center");
                    deleteOption = new GroupRadioButton();
                    deleteOption.DataBinding += new EventHandler(BindDeleteOption);
                    deleteOption.ID = "deleteOption";
                    deleteOptionCell.Controls.Add(deleteOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                if ((_displayedPermissions & PermissionColumns.Grant) == PermissionColumns.Grant)
                {
                    grantOptionCell = new TableCell();
                    row.Cells.Add(grantOptionCell);
                    grantOptionCell.Style.Add("text-align", "center");
                    grantOption = new GroupRadioButton();
                    grantOption.DataBinding += new EventHandler(BindGrantOption);
                    grantOption.ID = "grantOption";
                    grantOptionCell.Controls.Add(grantOption);

                    td = new TableCell();
                    row.Cells.Add(td);
                }

                inheritedOptionCell = new TableCell();
                row.Cells.Add(inheritedOptionCell);
                inheritedOptionCell.Style.Add("text-align", "center");
                inheritedOption = new GroupRadioButton();
                inheritedOption.DataBinding += new EventHandler(BindInheritedOption);
                inheritedOption.ID = "inheritedOption";
                inheritedOptionCell.Controls.Add(inheritedOption);

                inheritedInfoCell = new TableCell();
                row.Cells.Add(inheritedInfoCell);
                inheritedInfo = new Literal();
                inheritedInfoCell.Controls.Add(inheritedInfo);
                inheritedInfo.ID = "inheritedInfo";

                hiddenIDCell = new TableCell();
                row.Cells.Add(hiddenIDCell);
                dataFieldId = new HiddenField();
                dataFieldId.DataBinding += new EventHandler(BindDataFieldId);
                dataFieldId.ID = "dataFieldId";
                hiddenIDCell.Controls.Add(dataFieldId);
            }

            #endregion

        }

        #endregion

    }
}
